#ifndef HEAPSORT_H_
#define HEAPSORT_H_

#include <string>
#include <fstream>
#include <stdexcept>
#include "Heap.h"
#include "Buffer.hpp"
#include "Merger.h"
#include "../IndiceBooleano/RegistroOcurrencia.h"


class HeapSort {
	private:
		Merger fusorParticiones;
		std::fstream _archDesordenado;

		// Los elementos para el ordenamiento en heaps
		Heap<RegistroOcurrencia> _heap;
		Buffer<RegistroOcurrencia> _buffEntrada;
		Buffer<RegistroOcurrencia> _buffSalida;
		Buffer<RegistroOcurrencia> _buffCongelamiento;

		// Para comunicar el resultado del ordenamiento de las particiones
		enum Resultado { OK = 0, ENTRADA_VACIA = 1, CONGELADOR_LLENO = 2, SALIDA_LLENA = 4, HEAP_VACIO = 8 };

		// Permite inicializar los buffers y el heap
		bool initHeap();
		bool cargarBuffer(Buffer<RegistroOcurrencia>& buff);
		void cargarHeap(Buffer<RegistroOcurrencia>& buff, Heap<RegistroOcurrencia>& heap);

		// Realiza el ordenamiento hasta llenar el buffer de salida, el de congelamiento o vaciar el heap
		Resultado ordenarParticion(bool archivoVacio);
		void crearParticion(Buffer<RegistroOcurrencia>& buff, int orden);
		void descongelarBuffer(Buffer<RegistroOcurrencia>& buff, int nroParticion);

		// Si es posible ejecuta una selección natural de elementos
		bool naturalSelection(RegistroOcurrencia reg);
		Resultado evaluarBuffers(bool archivoVacio) const;

	public:
		HeapSort(std::string nomArchDesordenado, unsigned int cantElem = 100);
		virtual ~HeapSort();

		// Inicializa todo para el ordenamiento
		bool init(std::string nomArchFinal);

		// Realiza el ordenamiento en si
		void sort();
};

#endif /* HEAPSORT_H_ */
